package com.star.io.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @Description Netty的服务端
 * @Author powder
 * @Date 2024/9/14
 * @Version 1.0
 **/
public class Server {

    private final int port;

    public Server(int port) {
        this.port = port;
    }

    public void run() {
        // Netty：异步事件驱动，非阻塞IO，通过Selector机制实现一个线程同时处理多个连接
        //创建两个线程组 boosGroup、workerGroup
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //创建服务端的启动对象，设置参数
            ServerBootstrap bootstrap = new ServerBootstrap();
            //设置两个线程组boosGroup和workerGroup
            bootstrap.group(bossGroup, workerGroup)
                    //设置服务端通道实现类型
                    .channel(NioServerSocketChannel.class)
                    //设置线程队列得到连接个数
                    .option(ChannelOption.SO_BACKLOG, 128)
                    //设置保持活动连接状态
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    //使用匿名内部类的形式初始化通道对象
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) {
                            //给pipeline管道设置处理器
                            socketChannel.pipeline().addLast(new MyServerHandler());
                        }
                    });//给workerGroup的EventLoop对应的管道设置处理器
            System.out.println("服务端启动成功...");
            //绑定端口号，启动服务端 连接到远程节点，阻塞等待直到连接完成
            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            //对关闭通道进行监听 阻塞，直到Channel关闭
            channelFuture.channel().closeFuture().sync();

            //添加监听器
            //使用匿名内部类，ChannelFutureListener接口
            //重写operationComplete方法
            channelFuture.addListener((ChannelFutureListener) future -> {
                //判断是否操作成功
                if (future.isSuccess()) {
                    System.out.println("连接成功");
                } else {
                    System.out.println("连接失败");
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
